var fs = module.require('fs');
var path = require("path");

class FileUtil {
    /**
     * 复制单独文件用的函数。==================================================================
     * @param {*} src 被复制的文件的路径。
     * @param {*} dst 复制到的目标的路径。
     */
    static CopyFile(src, dst) {
        var dstPath = path.dirname(dst);
        /**只有目标目录存在才执行拷贝指令。 */
        if (fs.existsSync(dstPath) == true) {
            fs.writeFileSync(dst, fs.readFileSync(src));
        }
    }

    /**
     * 根据配置数据复制文件。=================================================================
     * @param {*} configList 这个是一个字符串的二维数组，结构如下：
     * [
     *   [
     *      原始路径1,
     *      复制到的路径1，
     *      复制到的路径2
     *   ],
     *   [
     *      原始路径2,
     *      复制到的路径1，
     *      复制到的路径2
     *   ]
     * ]
     * 注意：里面只能写文件的路径，不要写文件夹的路径。
     */
    static CopyFileByConfigData(configList) {
        configList.forEach((dataArr) => {
            /**第一个目录。------------------------------------- */
            let src = dataArr[0]
            /**拷贝到后面的目录。------------------------------- */
            for (let i = 1; i < dataArr.length; i++) {
                this.CopyFile(src, dataArr[i])
            }
        });
    }

    /**
     * 复制文件夹的方法。===================================================================
     * @param {*} src 被复制的文件夹。
     * @param {*} dest 文件夹要复制到的位置。
     * @returns 
     */
    static CopyDirectory(src, dest) {
        if (fs.existsSync(dest) == false) {
            /**取得上一级复制到的文件夹。---------------- */
            var parentPath = path.dirname(dest);
            /**如果上一级存在可以复制。------------------ */
            if (fs.existsSync(parentPath) == true) {
                fs.mkdirSync(dest);
            }
            /**上一级不存在，就不要复制了。---------------*/
            else {
                return false;
            }
        }
        if (fs.existsSync(src) == false) {
            return false;
        }
        var dirs = fs.readdirSync(src);
        dirs.forEach(function (item) {
            var item_path = path.join(src, item);
            var temp = fs.statSync(item_path);
            if (temp.isFile()) { // 是文件
                fs.copyFileSync(item_path, path.join(dest, item));
            } else if (temp.isDirectory()) { // 是目录
                FileUtil.CopyDirectory(item_path, path.join(dest, item));
            }
        });
    }

    /**
     * 根据配置数据复制文件夹。=================================================================
     * @param {*} configList 这个是一个字符串的二维数组，结构如下：
     * [
     *   [
     *      原始路径1,
     *      复制到的路径1，
     *      复制到的路径2
     *   ],
     *   [
     *      原始路径2,
     *      复制到的路径1，
     *      复制到的路径2
     *   ]
     * ]
     * 使用范例：
     * var dirCopyJson = [
     *   [
     *     "C:\\xampp\\htdocs\\hgProject\\ts\\",
     *     "C:\\Users\\zj\\Desktop\\SourceCode\\ZJ\\hgProject\\ts\\"
     *   ]
     * ]
     * tool.FileUtil.CopyDirectoryByConfigData(dirCopyJson);
     * 注意：里面只能写文件夹的路径，不要写文件的路径。
     */
    static CopyDirectoryByConfigData(configList) {
        configList.forEach((dataArr) => {
            /**第一个目录。------------------------------------- */
            let src = dataArr[0]
            /**拷贝到后面的目录。------------------------------- */
            for (let i = 1; i < dataArr.length; i++) {
                FileUtil.CopyDirectory(src, dataArr[i])
            }
        });
    }


    /**
     * 根据配置数据复制文件夹或文件夹。=================================================================
     * @param {*} configList 这个是一个字符串的二维数组，结构如下：
     * [
     *   [
     *      原始路径1,
     *      复制到的路径1，
     *      复制到的路径2
     *   ],
     *   [
     *      原始路径2,
     *      复制到的路径1，
     *      复制到的路径2
     *   ]
     * ]
     * 使用范例：
     * var copyCofig = [
     *   [
     *     "C:\\xampp\\htdocs\\hgProject\\ts\\",
     *     "C:\\Users\\zj\\Desktop\\SourceCode\\ZJ\\hgProject\\ts\\"
     *   ],
     *   [
     *     "C:\\abc.txt",
     *     "D:\\aa\abc.txt"
     *   ]
     * ]
     * tool.FileUtil.CopyDirectoryByConfigData(copyCofig);
     * 注意：里面可以写文件夹路径，也可以写文件的路径。
     */
    static CopyDirectoryOrFileByConfigData(configList) {
        configList.forEach((dataArr) => {
            /**第一个目录。------------------------------------- */
            let src = dataArr[0]
            //获取扩展名。
            let stat = fs.statSync(src);
            //如果是文件夹的话。
            if (stat.isDirectory()) {
                for (let i = 1; i < dataArr.length; i++) {
                    FileUtil.CopyDirectory(src, dataArr[i]);
                }
            }
            //如果是文件的话。
            else {
                for (let i = 1; i < dataArr.length; i++) {
                    FileUtil.CopyFile(src, dataArr[i])
                }
            }
        });
    }

    /**
     * 删除指定的文件。=================================================================
     * @param {*} url 要删除哪个文件,url写这里。
     * 使用范例：tool.FileUtil.DeleteFile("C:\\Users\\zj\\Desktop\\新建文件夹\\sheng.jpg")
     */
    static DeleteFile(path) {
        if (fs.existsSync(path)) {
            fs.unlinkSync(path);
        }
    }

    /**
     * 删除指定文件夹的方法。=============================================================
     * @param {*} path 
     * 使用范例：tool.FileUtil.DeleteDirectory("C:\\Users\\zj\\Desktop\\新建文件夹\\1\\");
     */
    static DeleteDirectory(pathUrl) {
        //如果路径存在的话。----------------------------------
        if (fs.existsSync(pathUrl)) {
            var files = fs.readdirSync(pathUrl);
            files.forEach(function (file, index) {
                var curPath = path.join(pathUrl, file);
                //碰到文件夹的话，递归。----------------------
                if (fs.statSync(curPath).isDirectory()) {
                    FileUtil.DeleteDirectory(curPath);
                }
                //碰到文件的话，直接删除。--------------------
                else {
                    fs.unlinkSync(curPath);
                }
            });
            //再删除文件夹本身。-----------------------------
            fs.rmdirSync(pathUrl);
        }
    }

    /**
     * 剪切文件。不管目标的文件夹是否存在，都会硬性剪切过去。=========================================================
     * @param {*} src 被剪切的文件路径。
     * @param {*} dst 剪切到的位置的路径。
     */
    static MoveFile(src, dst) {
        //前提是被剪切的文件存在，如果不存在没必要运行下去。--------------------------------
        if (fs.existsSync(src) == true) {
            //检查剪切目标的文件夹是否存在，如果目标路径不存在，先把对应的文件夹先创建起来。
            var targetDirectory = path.dirname(dst);
            if (fs.existsSync(targetDirectory) == false) {
                FileUtil.MakeMultistageDirectory(targetDirectory);
            }
            //开始剪切文件。--------------------------------------------------------------
            fs.renameSync(src, dst);
        }
    }

    /**
     * 可以一路创建多层文件夹，不管这些文件夹原来存在与否，都可以一步生成。===========================================
     * @param {*} dirname 
     * @returns 要创建的路径直接写在这里面。
     * 使用范例：tool.FileUtil.MakeMultistageDirectory("C:\\Users\\zj\\Desktop\\新建文件夹\\3\\2\\3\\4\\5\\6\\7\\8\\9\\10\\11\\12\\");
     */
    static MakeMultistageDirectory(dirname) {
        if (fs.existsSync(dirname)) {
            return true;
        } else {
            if (FileUtil.MakeMultistageDirectory(path.dirname(dirname))) {
                fs.mkdirSync(dirname);
                return true;
            }
        }
    }
}
exports.FileUtil = FileUtil;
